#################################################################
#                          _ooOoo_                               #
#                         o8888888o                              #
#                         88" . "88                              #
#                         (| ^_^ |)                              #
#                         O\  =  /O                              #
#                      ____/`---'\____                           #
#                    .'  \\|     |#  `.                          #
#                   /  \\|||  :  |||#  \                         #
#                  /  _||||| -:- |||||-  \                       #
#                  |   | \\\  -  #/ |   |                        #
#                  | \_|  ''\---/''  |   |                       #
#                  \  .-\__  `-`  ___/-. /                       #
#                ___`. .'  /--.--\  `. . ___                     #
#              ."" '<  `.___\_<|>_/___.'  >'"".                  #
#            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 #
#            \  \ `-.   \_ __\ /__ _/   .-` /  /                 #
#      ========`-.____`-.___\_____/___.-`____.-'========         #
#                           `=---='                              #
#      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        #
#         佛祖保佑       永无BUG     永不修改                     #
##################################################################
import logging
from logging.handlers import RotatingFileHandler
import sys, os
import time
from rich.logging import RichHandler
import tomlkit
import asyncio
import copy
from typing import cast, Dict, Any
import signal

time_ = time.time()
dir_path = os.path.dirname(os.path.abspath(__file__)).replace("\\", "/")
sys.path.append(dir_path)
import fun

# 读取配置文件
with open(f"{dir_path}/config.toml", "r", encoding="utf-8") as f:
    original_configuration = cast(Dict, tomlkit.parse(f.read()))

if original_configuration["advanced"]["dir_path"] != "":
    dir_path = original_configuration["advanced"]["dir_path"]
if not os.path.isabs(original_configuration["log"]["save_path"]):
    logs_save_path = os.path.join(
        original_configuration["advanced"]["dir_path"],
        original_configuration["log"]["save_path"],
    )
else:
    logs_save_path = original_configuration["log"]["save_path"]

# 设置日志
log = logging.getLogger(__name__)
log.setLevel(original_configuration["log"]["level"])
formatter = logging.Formatter(original_configuration["log"]["format"])
os.makedirs(logs_save_path, exist_ok=True)
handlers = [
    RichHandler(),
    RotatingFileHandler(
        filename=os.path.join(
            logs_save_path,
            original_configuration["log"]["name"],
        ),
        maxBytes=eval(original_configuration["log"]["maxBytes"]),
        backupCount=original_configuration["log"]["backupCount"],
        mode=original_configuration["log"]["mode"],
        encoding=original_configuration["log"]["encoding"],
    ),
]
handlers[1].setFormatter(formatter)
# handlers[0].setFormatter(formatter)
log.addHandler(handlers[0])
log.addHandler(handlers[1])

import Hotspot_module


log.info(f"程序启用, 初始化耗时{round(time.time()-time_, 2)}秒")
del time_
log.debug(f"配置文件: {original_configuration}")


def read_config(config_path: str = f"{dir_path}/config.toml") -> dict[str, Any]:
    with open(config_path, "r", encoding="utf-8") as f:
        return cast(dict, tomlkit.parse(f.read()))


def write_config(config: dict, config_path: str = f"{dir_path}/config.toml"):
    with open(config_path, "w", encoding="utf-8") as f:
        f.write(tomlkit.dumps(config))


def update_RotatingFileHandler_log_config(**args):
    handler = RotatingFileHandler(**args)
    handler.setFormatter(formatter)
    global log
    log.removeHandler(log.handlers[1])
    log.addHandler(handler)


def use_config_update_log_config(config: dict, log: logging.Logger = log):
    update_RotatingFileHandler_log_config(
        filename=os.path.join(
            config["log"]["save_path"],
            config["log"]["name"],
        ),
        maxBytes=eval(config["log"]["maxBytes"]),
        backupCount=config["log"]["backupCount"],
        mode=config["log"]["mode"],
        encoding=config["log"]["encoding"],
    )
    log.setLevel(config["log"]["level"])


async def main():
    global original_configuration, dir_path, logs_save_path
    hotspoter = Hotspot_module.HotspotManager(
        original_configuration["hotspot"]["ssid"],
        original_configuration["hotspot"]["password"],
    )
    hotspot_shutdown_records: list[float] = []  # 记录(在窗口期内)热点关闭时间
    log.info("热点管理器初始化成功")
    while original_configuration["hotspot"]["enable"]:
        try:
            # 热加载配置文件
            config = read_config()
            if config["advanced"]["dir_path"] != "":
                dir_path = config["advanced"]["dir_path"]
            if not os.path.isabs(config["log"]["save_path"]):
                logs_save_path = os.path.join(
                    dir_path,
                    config["log"]["save_path"],
                )
            if config != original_configuration:
                log.info("配置文件更改")
                log.debug(f"原配置: {original_configuration}")
                log.debug(f"新配置: {config}")
                use_config_update_log_config(config)
                original_configuration = copy.deepcopy(config)

            # 检查热点状态
            hotspot_status = hotspoter.check_hotspot_status()

            if not hotspot_status["is_on"]:
                log.info("热点未启动, 尝试启动热点")

                # 更新热点关闭记录
                hotspot_shutdown_records.append(time.time())
                # 删除大于窗口期的记录
                while (
                    time.time() - hotspot_shutdown_records[0]
                    > config["hotspot"]["monitor_window"]
                ):
                    hotspot_shutdown_records.pop(0)
                # 如果窗口期内热点关闭次数大于阈值, 则使程序休眠
                if len(hotspot_shutdown_records) > config["hotspot"]["max_closes"]:
                    log.warning(
                        f"热点关闭次数超过阈值, 程序休眠{config['hotspot']['cooldown_duration']}秒"
                    )
                    await asyncio.sleep(eval(config["hotspot"]["cooldown_duration"]))

                await hotspoter._start_hotspot_async(
                    ssid=config["hotspot"]["ssid"],
                    password=config["hotspot"]["password"],
                )
                log.debug("热点启动成功")
            else:
                log.debug("热点已启动")
            if (hotspot_status["password"], hotspot_status["ssid"]) != (
                config["hotspot"]["password"],
                config["hotspot"]["ssid"],
            ):
                if (
                    hotspot_status["password"],
                    hotspot_status["ssid"],
                ) == (
                    hotspoter.password,
                    hotspoter.ssid,
                ):  # 密码或SSID通过配置文件修改
                    try:
                        hotspoter.password = config["hotspot"]["password"]
                        hotspoter.ssid = config["hotspot"]["ssid"]
                        log.info("密码或SSID被配置文件更改, 正在同步配置...")
                        if hotspoter.check_ssid_and_password(
                            config["hotspot"]["ssid"],
                            config["hotspot"]["password"],
                            return_=True,
                        ):  # 密码格式正确
                            await hotspoter._update_hotspot_credentials_async(
                                config["hotspot"]["ssid"], config["hotspot"]["password"]
                            )
                            log.info("密码或SSID已更新")
                        else:  # 密码格式错误
                            config["hotspot"]["ssid"] = hotspoter.ssid
                            config["hotspot"]["password"] = hotspoter.password
                            original_configuration["hotspot"]["ssid"] = hotspoter.ssid
                            original_configuration["hotspot"][
                                "password"
                            ] = hotspoter.password
                            write_config(config)
                            log.warning("密码或SSID格式错误, 配置项已被重置")
                    except Exception as e:
                        log.error(f"在同步外部热点配置时发生错误: {e}")
                else:  # 密码或SSID被外部因素更改
                    if not config["hotspot"][
                        "prevent_external_ssid_and_password_change"
                    ]:
                        try:
                            log.info("密码或SSID被外部因素更改, 正在同步配置...")
                            # 系统已经检查过密码格式, 不需要再次检查
                            new_ssid = hotspot_status["ssid"]
                            new_password = hotspot_status["password"]
                            config["hotspot"]["ssid"] = new_ssid
                            config["hotspot"]["password"] = new_password
                            original_configuration["hotspot"]["ssid"] = new_ssid
                            original_configuration["hotspot"]["password"] = new_password
                            hotspoter.ssid = new_ssid
                            hotspoter.password = new_password
                            write_config(config)
                            log.info("密码或SSID已更新")
                        except Exception as e:
                            log.error(f"在同步外部热点配置时发生错误: {e}")
                    else:  # 阻止外部修改
                        try:
                            log.info("密码或SSID被外部因素更改, 尝试阻止...")
                            hotspoter.ssid = config["hotspot"]["ssid"]
                            hotspoter.password = config["hotspot"]["password"]
                            await hotspoter._update_hotspot_credentials_async()
                            log.info("已阻止外部修改")
                        except Exception as e:
                            log.error(f"在阻止外部修改时发生错误: {e}")

            await asyncio.sleep(config["program"]["refresh_interval"])
        except KeyboardInterrupt:
            pass
        # except Exception as e:
        #     log.error(f"发生错误: {e}")


if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt as e:
        log.info("程序被手动停止")
        if original_configuration["program"]["shutdown_on_exit"]:
            log.info("正在关闭热点...")
            Hotspot_module.HotspotManager("11", "114514514").stop_hotspot()
            log.info("热点已关闭")
